package token

import (
	"fmt"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
	"time"
)

type Context struct {
	ID       uint64
	UserName string
}

// 生成token
func Sign(c Context, secret string) (tokenString string, err error) {
	if secret == "" {
		secret = viper.GetString("jwt_secret")
	}
	//生成token内容
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"id":       c.ID,
		"username": c.UserName,
		"nbf":      time.Now().Unix(),
		"iat":      time.Now().Unix(),
		"exp":      time.Now().Unix() + viper.GetInt64("expir"), //过期时间
	})
	//生成token
	tokenString, err = token.SignedString([]byte(secret))
	return
}

// 验证token
func ValidataToken(c *gin.Context) (*Context, error) {
	//客户端将token放在http头部字段 -- Token里面 来发起请求
	//服务端就获取http头部字段Token保存的 tokenstring
	fmt.Println("进行token验证。。。")
	tokenstring := c.Request.Header.Get("Token")
	ctx := &Context{}

	if tokenstring == "" {
		return ctx, fmt.Errorf("token为空!")
	}

	//解析token
	token, err := jwt.Parse(tokenstring, secretFunc)
	if err != nil {
		return ctx, err
	} else if claims, ok := token.Claims.(jwt.MapClaims); ok {
		ctx.ID = uint64(claims["id"].(float64))
		ctx.UserName = claims["username"].(string)
		return ctx, nil
	} else {
		return ctx, fmt.Errorf("无法解析!%s", err)
	}

}

// 支持多种secretKey
func secretFunc(token *jwt.Token) (interface{}, error) {
	return []byte(viper.GetString("jwt_secret")), nil
}
